package com.abing.api.client;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import cn.hutool.json.JSONUtil;
import com.abing.api.enums.SignHeaderEnum;
import com.abing.api.model.FormDataField;
import com.abing.api.model.NameValueField;
import com.abing.api.model.RequestBodyOption;
import com.abing.api.model.StarryApiRequest;
import com.abing.api.utils.QueryStringUtils;
import com.abing.api.utils.SignUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author CaptainBing
 * @Date 2024/8/21 20:40
 * @Description
 */
@Data
@Slf4j
@AllArgsConstructor
public class StarryApiClient {

    private String accessKey;

    private String secretKey;

    private String initUrl;

    public StarryApiClient(String accessKey, String secretKey) {
        this.accessKey = accessKey;
        this.secretKey = secretKey;
    }

    public String sayHello(String text){
        System.out.println("what can i say: " + text);
        return text;
    }

    public String starryApiSend(StarryApiRequest starryApiRequest){

        HttpRequest httpRequest = onAssemblyRequest(starryApiRequest);
        httpRequest.addHeaders(getSignHeaderMap());
        HttpResponse httpResponse = httpRequest.execute();

        return httpResponse.body();
    }

    /**
     * 通用组装请求参数方法
     * @param starryApiRequest
     * @return
     */
    public HttpRequest onAssemblyRequest(StarryApiRequest starryApiRequest){

        String url = starryApiRequest.getUrl();
        String method = starryApiRequest.getMethod().toUpperCase();

        List<NameValueField> requestHeaderList = starryApiRequest.getRequestHeader();
        Map<String, String> requestHeaderMap = requestHeaderList
                .stream()
                .collect(Collectors.toMap(NameValueField::getName, NameValueField::getValue));

        List<NameValueField> requestParamList = starryApiRequest.getRequestParam();
        Map<String, NameValueField> requestParamMap = requestParamList
                .stream()
                .collect(Collectors.toMap(NameValueField::getKey, e->e));

        // query param 拼接路径
        url = QueryStringUtils.buildQueryString(url, requestParamMap);

        int timeout = starryApiRequest.getTimeout();
        boolean isOverride = starryApiRequest.getHeaderIsOverride();

        HttpRequest httpRequest = HttpRequest.of(url)
                                             .method(Method.valueOf(method))
                                             .headerMap(requestHeaderMap, isOverride)
                                             .timeout(timeout);


        // 请求体参数设置
        RequestBodyOption requestBodyOption = starryApiRequest.getRequestBodyOption();
        Object requestBody = starryApiRequest.getRequestBodyOption().getRequestBody();
        RequestBodyOption.BodyType bodyType = requestBodyOption.getBodyType();

        if (bodyType == RequestBodyOption.BodyType.RAW){
            if (requestBodyOption.getRequestBodyType() == RequestBodyOption.RequestBodyType.JSON){
                httpRequest = httpRequest.body(String.valueOf(requestBody));
            }
            // TODO XML JAVASCRIPT PLAIN HTML
        }

        if (bodyType == RequestBodyOption.BodyType.URLENCODED){

            List<FormDataField> formDataList = JSONUtil.toList(JSONUtil.toJsonStr(requestBody), FormDataField.class);

            Map<String, NameValueField> urlEncodeMap = formDataList.stream()
                                                      .collect(Collectors.toMap(FormDataField::getName, e->{
                                                          String key = e.getKey();
                                                          String name = e.getName();
                                                          String value = String.valueOf(e.getValue());
                                                          NameValueField nameValueField = new NameValueField();
                                                          nameValueField.setKey(key);
                                                          nameValueField.setName(name);
                                                          nameValueField.setValue(value);
                                                          return nameValueField;
                                                      }));
            url = QueryStringUtils.buildQueryString(url, urlEncodeMap);
            httpRequest.setUrl(url);

        }

        if (bodyType == RequestBodyOption.BodyType.FORM_DATA){
            List<FormDataField> formData = JSONUtil.toList(JSONUtil.toJsonStr(requestBody), FormDataField.class);
            Map<String, Object> formDataMap = formData.stream()
                                                      .collect(Collectors.toMap(FormDataField::getName, FormDataField::getValue));
            httpRequest = httpRequest.form(formDataMap);
        }

        log.info("调用API接口 请求路径:{}",url);

        return httpRequest;

    }

    private Map<String,String> getSignHeaderMap(){
        Map<String,String> headerMap = new HashMap<>(4);
        headerMap.put(SignHeaderEnum.X_ACCESS_KEY.getText(), accessKey);
        headerMap.put(SignHeaderEnum.X_NONCE.getText(), RandomUtil.randomString(8));
        String timestamp = String.valueOf(System.currentTimeMillis());
        headerMap.put(SignHeaderEnum.X_TIMESTAMP.getText(), timestamp);
        String sign = SignUtils.genSign(timestamp, secretKey);
        headerMap.put(SignHeaderEnum.X_SIGN.getText(), sign);
        return headerMap;
    }

}
